package com.vc.videosdk


import android.os.Looper
import android.util.Log
import com.vc.videosdk.interfaces.PreviewConnectListener
import com.vc.videosdk.interfaces.WebSocketConnectListener
import com.vc.videosdk.xlog.XLogUtil
import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import java.net.URI
import java.nio.ByteBuffer
import java.util.Collections


/**

 * @Author : wy

 * @Time : On 2024/9/14 13:50

 * @Description : WebSocketManager

 */
class WebSocketManager private constructor() {
    private val TAG="WebSocketManager_"
    private val TAG_ERROR="WebSocketManager_Error"
    private var clients = Collections.synchronizedList(ArrayList<ClientConnect>())

    companion object {
        private var singleInstance: WebSocketManager? = null
            get() {
                // 懒汉模式
                if (null == field) {
                    field = WebSocketManager()
                }
                return field
            }

        @Synchronized // 添加注解，线程同步，线程安全
        fun getInstance(): WebSocketManager {
            return singleInstance!! // 表示非空时执行
        }
    }


    /**
     * 添加客户端连接
     */
    fun addClient(
        instanceId: String,
        wsAddress:String,
        ip: String,
        token: String,
        deviceId: String,
        listener: WebSocketConnectListener
    ): ClientConnect? {
        try {
            //已经连接,不连接
            var clientConnect: ClientConnect? = isConnected(instanceId)
            if (clientConnect != null) {
                return clientConnect
            }


            // var address="ws://192.168.204.72:44912/ws"
            //websocket 连接格式：
            // ws://192.168.134.11:49912?ip=192.168.11.49&Authorization=dd898e31d6efe2892a935470b36a393f9c95fdb26ac010ea2342da3ac79d96ff73fd5f024804c302742b99523b900719

            var connectUrl= "$wsAddress?ip=$ip&Authorization=$token&Device-ID=$deviceId"
            XLogUtil.d("${TAG}connect connectUrl :$connectUrl,,,,wsAddress:$wsAddress,,,instanceId:$instanceId,,,deviceId:$deviceId")

            //地址格式:ws://192.168.134.11:49912=192.168.11.49

//            if(address.isNullOrEmpty()&&!address.contains("=")){
//                XLogUtil.e("WebSocketManager wsAddress格式不正确")
//                return null
//            }
//
//            val addressList=address.split("=")
//            val wsAddress=addressList[0]
//            val ip=addressList[1]



            var client = object : WebSocketClient(URI.create(connectUrl)) {
                override fun onOpen(handshakedata: ServerHandshake) {
                    // 连接打开时的回调,连接上才开始发送请求
                    XLogUtil.d("${TAG}CONNECT OPEN  URL:$connectUrl,,,打开连接:{$handshakedata.httpStatusMessage}")
                    listener.onOpen(handshakedata)
                }


                override fun onMessage(message: String) {
                    // 收到消息时的回调
                    //XLogUtil.d("WebSocketManager 收到消息:$message,,,,,url:$ip")
                    if (listener != null) {
                        listener.onRecMessage(message)
                    }

                }


                override fun onClose(code: Int, reason: String, remote: Boolean) {
                    // 连接关闭时的回调
                    // XLogUtil.d("WebSocketManager onClose code:$code,,,,,reason:$reason,,,remote:$remote")
                    if (listener != null) {
                        listener.onClose(code, reason, remote)
                    }
                }

                override fun onError(ex: Exception) {
                    // 发生错误时的回调
                    // XLogUtil.e("WebSocketManager onError Exception:${ex.message}")
                    if (listener != null) {
                        listener.onError(ex)
                    }
                }
            }

            var createClientConnect = ClientConnect(instanceId, ip, token, client)

            clients.add(createClientConnect)


           //client.addHeader("Authorization", token)
           // client.addHeader("ip", ip)

            client.connect()
            return createClientConnect
        } catch (e: Exception) {
            XLogUtil.e("{$TAG_ERROR}addClient Exception:" + e.message)
        }

        return null
    }


    /**
     * 预览图添加客户端连接(长连接)
     */
    fun addClient(
        instanceId: String,
        wsAddress:String,
        ip: String,
        token: String,
        deviceId:String,
        listener: PreviewConnectListener
    ): ClientConnect? {
        try {
            //已经连接,不连接
            var clientConnect: ClientConnect? = isConnected(instanceId)
            if (clientConnect != null) {
                return clientConnect
            }

           // val address = "ws://$ip:${Constant.WEB_SOCKET_PORT}"


            var connectUrl= "$wsAddress?ip=$ip&Authorization=$token&Device-ID=$deviceId"
            XLogUtil.d("${TAG}connect connectUrl :$connectUrl,,,,wsAddress:$wsAddress,,,instanceId:$instanceId,,,deviceId:$deviceId")


//            XLogUtil.d("WebSocketManager connect address :$ip")
            var client = object : WebSocketClient(URI.create(connectUrl)) {
                override fun onOpen(handshakedata: ServerHandshake) {
                    XLogUtil.d("${TAG}CONNECT OPEN  URL:$wsAddress,,,打开连接:{$handshakedata.httpStatusMessage}")
                    // 连接打开时的回调,连接上才开始发送请求
                    listener.onOpen(handshakedata)
                }


                override fun onMessage(message: String) {
                    // 收到消息时的回调
                    //XLogUtil.d("WebSocketManager 收到消息:$message,,,,,url:$ip")
                    if (listener != null) {
                        listener.onRecMessage(message)
                    }

                }

                override fun onMessage(bytes: ByteBuffer) {
                    XLogUtil.d("${TAG}收到预览图数据:$bytes,,,,len:${bytes.remaining()},,,是否在主线程${(Looper.getMainLooper() == Looper.myLooper())}")
                    listener.onMessage(bytes)
                }


                override fun onClose(code: Int, reason: String, remote: Boolean) {
                    // 连接关闭时的回调
                    //XLogUtil.d("WebSocketManager onClose code:$code,,,,,reason:$reason,,,remote:$remote")
                    if (listener != null) {
                        listener.onClose(code, reason, remote)
                    }
                }

                override fun onError(ex: Exception) {
                    // 发生错误时的回调
                    // XLogUtil.e("WebSocketManager onError Exception:${ex.message}")
                    if (listener != null) {
                        listener.onError(ex)
                    }
                }
            }

            var createClientConnect = ClientConnect(instanceId, ip, token, client)

            clients.add(createClientConnect)


            //client.addHeader("Authorization", token)

            client.connect()
            return createClientConnect
        } catch (e: Exception) {
            XLogUtil.e("${TAG_ERROR}preview addClient Exception" + e.message)
        }

        return null
    }


    /**
     * 判断是否连接
     */
    private  fun isConnected(instanceId: String): ClientConnect? {
//        for (clientConnect in clients) {
//            if (clientConnect.instanceId == instanceId) {
//                val client = clientConnect.client
//                if (client != null && (client.isOpen)) {
//                    return clientConnect
//                } else {
//                    clients.remove(clientConnect)
//                }
//            }
//        }
        try {
            synchronized(clients){
                val iterator=clients.iterator()
                while (iterator.hasNext()){
                    val clientConnect=iterator.next() as ClientConnect
                    if(clientConnect!=null&&(clientConnect.instanceId == instanceId)){
                        val client = clientConnect.client
                        if (client != null && (client.isOpen)) {
                            return clientConnect
                        } else {
                            iterator.remove()
                        }
                    }
                }
            }
        }catch (e:Exception){
            XLogUtil.e("${TAG_ERROR}isConnected Exception:${e.message}")
        }

        return null
    }

    /**
     * 根据instanceId获取连接
     */
    fun getClientConnect(instanceId: String) :ClientConnect?{
        return isConnected(instanceId)
    }




    /**
     * 给所有实例发送消息
     */
    fun sendMessage(message: String) {
        for (clientConnect in clients) {
            val client = clientConnect.client
            if (client.isOpen) {
                client.send(message)
            }
        }
    }


    /**
     * 向单个实例发送消息
     */
    fun sendMessage(message: String, instanceId: String) {
        for (clientConnect in clients) {
            if (instanceId == clientConnect.instanceId) {
                val client = clientConnect.client
                if (client.isOpen) {
                    client.send(message)
                    XLogUtil.d("${TAG}send message:$message,,,ip:{${clientConnect.ip}},,,,instanceId:$instanceId")
                } else {
                    XLogUtil.e("${TAG_ERROR}send message fail:$message,,,ip:{${clientConnect.ip}},,,,instanceId:$instanceId")
                }
            }
        }
    }


    /**
     * 向单个实例发送消息
     */
    fun sendMessage(client: WebSocketClient, message: String) {
        try {
            if (client.isOpen) {
                client.send(message)
                XLogUtil.d("${TAG}send message:$message,,,ip:{${client.remoteSocketAddress.address.hostAddress}}")
            } else {
                XLogUtil.e("${TAG_ERROR}send message fail:$message,,,connectStatus:{${client.isOpen}}")
            }
        }catch (e:Exception){
            XLogUtil.e("${TAG_ERROR}sendMessage Exception:${e.message}")
        }

    }


    /**
     * 关闭所有连接
     */
    fun closeAll() {
        for (clientConnect in clients) {
            val client = clientConnect.client
            if (client.isOpen) {
                client.close()
            }
        }
        clients.clear()
    }


    /**
     * 关闭某个连接
     */
    fun closeConnect(clientConnect: ClientConnect) {
        try {
            clientConnect?.apply {
                if (clients.contains(clientConnect)) {
                    val webSocketClient = clientConnect.client
                    if (webSocketClient != null && webSocketClient.isOpen) {
                        XLogUtil.d("${TAG}closeConnect:${clientConnect}")
                        webSocketClient.close()
                    }
                    clients.remove(clientConnect)
                }
            }
        } catch (e: Exception) {
            XLogUtil.e(
                "${TAG_ERROR}closeConnect Exception:${e.message},,,stackTraceToString:${e.stackTraceToString()},,,clientConnect:${clientConnect}"
            )
        }
    }
}